﻿package com.snzflash.components
{
	import com.snzflash.events.ComponentEvent;
	import flash.display.Sprite;
	import flash.events.Event;
	import com.snzflash.utils.StageDetector;
	
	/**
	 * Базовая конструкция для компонентов приложения
	 * @author firsoff maxim, tel: +79222345364, skype: maxim.firsoff
	 */
	public class ComponentBase extends Sprite
	{
		
		// PROPERTIES
	
		// public
		
		// protected
		protected var _eventListeners:Array;
		protected var _stageDetector:StageDetector;
		protected var _data:Object;
		protected var _changed:Boolean;
		protected var __width:Number;
		protected var __height:Number;
		// == STATIC==
		// дефолтные значения для высоты и ширины
		public static const DEFAULT_WIDTH:Number = 100;
		public static const DEFAULT_HEIGHT:Number = 100;
		
		// CONSTRUCTOR
		public function ComponentBase() 
		{
			super();
			init();
		};
		
		protected function init():void
		{
			_eventListeners = new Array();
			initProperties();
			initStageDetector();
			create();
			dispatchEvent(new ComponentEvent(ComponentEvent.CREATION_COMPLETE));;
		};
		
		protected function create():void
		{
			
		};
		
		protected function initProperties():void
		{
			width = DEFAULT_WIDTH;
			height = DEFAULT_HEIGHT
		};
		
		protected function initStageDetector():void
		{
			_stageDetector = new StageDetector(this);
			_stageDetector.addEventListener(StageDetector.ADDED_TO_STAGE,  onAddedToStage);
			_stageDetector.addEventListener(StageDetector.REMOVED_FROM_STAGE,  onRemovedFromStage);
		};
		
		protected function removeStageDetector():void 
		{
			_stageDetector.removeEventListener(StageDetector.ADDED_TO_STAGE,  onAddedToStage);
			_stageDetector.removeEventListener(StageDetector.REMOVED_FROM_STAGE,  onRemovedFromStage);
			_stageDetector.dispose();
			_stageDetector = null;
		}
		// METHODS
	
		// public
		
		/**
		 * Уничтожение
		 */
		public function destroy():void 
		{
			dispatchEvent(new ComponentEvent(ComponentEvent.DESTROY));
			removeStageDetector();
			destroyContent();
		};
		
		/**
		 * Сброс всех слушателей + внутренние события
		 */
		public function clearAllListeners():void 
		{
			for each(var i:Object  in _eventListeners) 
			{
				super.removeEventListener(i.type, i.listener, i.useCapture);
			};
			_eventListeners = new Array();
		}
		
		/**
		 * Переопределяем стандартный метод добавления
		 */
		override public function addEventListener(type:String, listener:Function, useCapture:Boolean = false, priority:int = 0, useWeakReference:Boolean = false):void 
		{
			_eventListeners.push( { type:type, listener:listener, useCapture:useCapture, priority:priority, useWeakReference:useWeakReference } );
			super.addEventListener(type, listener, useCapture, priority, useWeakReference);
		};
		
		override public function removeEventListener(type:String, listener:Function, useCapture:Boolean = false):void 
		{
			for each(var i:Object  in _eventListeners) 
			{
				//trace(i['type']);
				if (i.type == type && i.listener == listener && i.useCapture == useCapture)
				{
					_eventListeners.splice(_eventListeners.indexOf(i), 1);
					break;
				};
			}
			super.removeEventListener(type, listener, useCapture);
		};
		
		public function invalidate():void
		{
			_changed = true;
			if (stage) stage.invalidate();
		};
		// protected
		
		protected function destroyContent():void
		{
			dispatchEvent(new ComponentEvent(ComponentEvent.DESTROYED));
			clearAllListeners();
		};
		
		
		
		
		protected function updateDisplayList():void
		{
			
		};
		
		// getters/setters
		public function get data():Object { return _data; };
		
		public function set data(value:Object):void 
		{
			_data = value;
			 invalidate();
		};
		
		public function get changed():Boolean { return _changed; };
		
		override public function get width():Number { return __width; };
		
		override public function set width(value:Number):void 
		{
			__width = value;
			invalidate();
		};
		
		override public function get height():Number { return __height; };
		
		override public function set height(value:Number):void 
		{
			__height = value;
			invalidate();
		};
		
		public function get rawHeight():Number { return super.height; };
		
		public function set rawHeight(value:Number):void 
		{
			super.height = value;
			invalidate();
		};
		
		public function get rawWidth():Number { return super.width; };
		
		public function set rawWidth(value:Number):void 
		{
			super.width = value;
			invalidate();
		};
		// == STATIC==
		
		
		// HANDLERS
		
		/**
		 * если убрали со сцены - отписываемся от рендера
		 * @param	event
		 */
		protected function onRemovedFromStage(event:Event):void 
		{
			stage.removeEventListener(Event.RENDER, onStageRender);
		};
		
		/**
		 * При добавлении подписываемся на рендер
		 * @param	event
		 */
		protected function onAddedToStage(event:Event):void 
		{
			stage.addEventListener(Event.RENDER, onStageRender);
			invalidate();
		};
		
		/**
		 * При рендере - проверяем изменились ли свойства?
		 * если да - обновляем список
		 * @param	event
		 */
		protected function onStageRender(event:Event):void 
		{
			if (_changed) updateDisplayList();
			_changed = false;
		};
		
		
		
	};

};